package com.ykt.common.utils.page;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

/**
 * 包装查询到的分页数据
 *
 * @author: hualong
 * @date 2014年5月16日 下午8:58:45
 */
public class PageData<T> implements Serializable {
    private static final long serialVersionUID = 1L;

    public final static int DEFAULT_OFFSET = 0;
    public final static int DEFAULT_PAGE_NO = 1;
    public final static int DEFAULT_PAGE_SIZE = 20;

    /**
     * 存储返回的List结果
     */
    private List<T> pageData;

    /**
     * 查询起始行数
     */
    private int offset = DEFAULT_OFFSET;

    /**
     * 每页的记录数(每页尺寸)
     */
    private int pageSize = DEFAULT_PAGE_SIZE;

    /**
     * 总记录数
     */
    private int dataTotal;

    /**
     * 跳转页数，页数是从第一页是从1开始计算的
     */
    private int pageNo = DEFAULT_PAGE_NO;

    /**
     * 总页数
     */
    private int pageTotal;

    /**
     * 是否有上一页
     */
    private boolean prevPage = false;

    /**
     * 是否有下一页
     */
    private boolean nextPage = false;

    /**
     * 有些反序列化需要使用默认构造函数
     */
    public PageData() {

    }

    /**
     * 返回一个分页数据对象
     *
     * @param offset    起始行号
     * @param pageSize  每页记录数
     * @param dataTotal 总记录数
     * @return 分页数据对象
     */
    public PageData(int offset, int pageSize, int dataTotal) {
        this.offset = offset;
        this.pageSize = pageSize;
        this.dataTotal = dataTotal;
        this.refresh();
    }

    /**
     * 创建一个分页数据对象
     *
     * @param offset    起始行号，从0开始
     * @param pageSize  每页记录数
     * @param dataTotal 总记录数
     * @param pageData  当前页数据列表
     * @author: hualong
     */
    public PageData(List<T> pageData, int offset, int pageSize, int dataTotal) {
        this.offset = offset;
        this.pageSize = pageSize;
        this.dataTotal = dataTotal;
        this.pageData = pageData;
        this.refresh();
    }

    public <V> PageData<V> convert(List<V> pageData) {
        PageData<V> pd = new PageData<V>();
        pd.setOffset(offset);
        pd.setPageSize(pageSize);
        pd.setDataTotal(dataTotal);
        pd.setPageData(pageData);
        pd.refresh();
        return pd;
    }

    private void calcPageNo() {
        this.pageNo = offset / pageSize + 1;
    }

    public static int calcOffset(int pageNo, int pageSize) {
        pageNo = pageNo == 0 ? 1 : pageNo;
        return (pageNo - 1) * pageSize;
    }

    /**
     * 取总页数
     */
    private void calcPageTotal() {
        this.pageTotal = (int) Math.ceil(this.dataTotal * 1.000 / this.pageSize);
    }

    /**
     * 根据offset、pageSize、dataTotal计算pageNo、pageTotal，prevPage、nextPage属性
     */
    public void refresh() {
        this.calcPageNo();
        this.calcPageTotal();

        if (pageTotal <= 1) {
            prevPage = false;
            nextPage = false;
        } else if (pageNo == 1) {
            prevPage = false;
            nextPage = true;
        } else if (pageNo == pageTotal) {
            prevPage = true;
            nextPage = false;
        } else {
            prevPage = true;
            nextPage = true;
        }
    }


    /**
     * 查询时为入参，查询返回时为List结果
     *
     * @return
     * @author: hualong
     * @date: 2014年5月16日下午8:28:22
     */
    public List<T> getPageData() {
        return pageData;
    }

    /**
     * 设置查询入参或返回结果
     *
     * @param pageData 查询时为入参，查询返回时为List结果
     * @author: hualong
     * @date: 2014年5月16日下午8:29:07
     */
    public void setPageData(List<T> pageData) {
        this.pageData = pageData;
    }

    /**
     * 返回每页记录数
     */
    public int getPageSize() {
        return pageSize;
    }

    /**
     * 设置每页记录数，单独调用时需要执行refresh方法
     */
    public void setPageSize(int pageSize) {
        this.pageSize = pageSize;
    }

    /**
     * 返回行号，第一行为0
     */
    public int getOffset() {
        return offset;
    }

    /**
     * 设置行号，第一行为0，单独调用时需要执行refresh方法
     */
    public void setOffset(int offset) {
        this.offset = offset;
    }

    /**
     * 返回页号，第一页为1
     */
    public int getPageNo() {
        return pageNo;
    }

    /**
     * 返回当前页记录总数
     */
    public int getDataTotal() {
        return dataTotal;
    }

    /**
     * 设置当前页记录总数，单独调用时需要执行refresh方法
     */
    public void setDataTotal(int dataTotal) {
        this.dataTotal = dataTotal;
    }

    /**
     * 返回分页总数
     */
    public int getPageTotal() {
        return pageTotal;
    }

    /**
     * 返回是否有前一页，有为true否为false
     */
    public boolean hasPrevPage() {
        return prevPage;
    }

    /**
     * 返回是否有后一页，有为true否为false
     */
    public boolean hasNextPage() {
        return nextPage;
    }

    /**
     * 取得List的第N页的subList
     *
     * @param list     要分页的list
     * @param offset
     * @param pageSize
     * @return List
     */
    public static <T> List<T> subList(List<T> list, int offset, int pageSize) {
        // 开始结束位置
        int begin = offset > list.size() ? list.size() : offset;
        int end = (offset + pageSize) > list.size() ? list.size() : (offset + pageSize);

        // 返回分页数据
        return new ArrayList<>(list.subList(begin, end));
    }

    /**
     * 取得List的第N页的DataPage对象
     *
     * @param list     要分页的list
     * @param offset   起始行号
     * @param pageSize 每页记录数
     * @return List 一页的数据
     */
    public static <T> PageData<T> pageList(List<T> list, int offset, int pageSize) {
        List<T> l = subList(list, offset, pageSize);
        return new PageData<>(l, offset, pageSize, list.size());
    }

    @Override
    public String toString() {
        return String.format(
                "PageParam [p=%s, pageNo=%s, pageSize=%s, dataTotal=%s, pageTotal=%s, prevPage=%s, nextPage=%s]",
                pageData, pageNo, pageSize, dataTotal, pageTotal, prevPage, nextPage);
    }

    public static void main(String[] args) {
        List<String> l = new ArrayList<>();
        l.add("123456");
        l.add("654321");

        PageData<String> p = pageList(l, 0, 1);
        System.out.println(p);
    }
}
